package com.woniuxy.auth.config;/*
@author houguai
@create 2021-03-03 12:02
*/

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.woniuxy.auth.entity.Rbac_perm;
import com.woniuxy.auth.filter.JwtFilter;
import com.woniuxy.auth.mapper.Rbac_permMapper;
import com.woniuxy.auth.shiro.DBRealm;
import com.woniuxy.auth.shiro.JwtRealm;
import com.woniuxy.auth.shiro.MultiAuthenticator;
import com.woniuxy.auth.shiro.MyPermissionsAuthorzationFilter;
import org.apache.shiro.authc.pam.FirstSuccessfulStrategy;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.apache.shiro.mgt.SecurityManager;

import javax.servlet.Filter;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;



@Configuration  //配置类标志
public class ShiroConfiguration {
    private static  final Logger logger = LoggerFactory.getLogger(ShiroConfiguration.class);

    //1.配置DBrealm：域对象，调用service获取用户的账号密码、权限信息  自定义
    @Bean   //<bean>  默认以方法名作为id：此处就是realm
    public DBRealm dbRealm(){
        logger.info("创建DBrealm");
        return new DBRealm();
    }
    //2.配置Jwtrealm：域对象，调用service获取用户的账号密码、权限信息  自定义
    @Bean
    public JwtRealm jwtReam(){
        logger.info("创建Jwtrealm");
        return new JwtRealm();
    }




    //自定义mapFactory，增加数据库认证
    @Bean
    public PermMapFactoryBean permMapFactoryBean() {
        return new PermMapFactoryBean();
    }


    //2.安全管理器（核心）
    @Bean   //参数将相当于  <property ref = "realm">
    public DefaultWebSecurityManager securityManager(DBRealm dbRealm, JwtRealm jwtRealm){
        DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
        //设置realm
        //manager.setRealm(realm);
        //manager.setRealms(Arrays.asList(realm, jwtRealm));

//        ModularRealmAuthenticator authenticator=new ModularRealmAuthenticator();
        //复数Realm编辑
        MultiAuthenticator authenticator=new MultiAuthenticator();
        authenticator.setRealms(Arrays.asList(dbRealm, jwtRealm));
        authenticator.setAuthenticationStrategy(new FirstSuccessfulStrategy());
        //将认证系统注入管理器
        manager.setAuthenticator(authenticator);
        //授权给Dbrealm
        manager.setAuthorizer(dbRealm);

        return manager;
    }

    //3.创建自定义过滤器bean
    @Bean
    public JwtFilter jwtFilter(){
        return new JwtFilter();
    }

    //4.自定义过滤认证。重写源码增强功能
    @Bean
    public MyPermissionsAuthorzationFilter myPermissionsAuthorzationFilter(){
        return new MyPermissionsAuthorzationFilter();
    }

    /**
     * 3.shiro过滤器
     * 主要来指定哪些请求需要认证、哪些不需要、哪些需要什么样的权限
     */
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager){
        ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();
        //配置安全管理器
        factoryBean.setSecurityManager(securityManager);
//        //配置没有权限时要请求的url(页面、后台url)
//        factoryBean.setUnauthorizedUrl("/html/error.html");//如果在后台跳 表明前后端不分离
        //需要登录但是又没有登录时，自动跳转到指定的页面获取请求后台的url
//        factoryBean.setLoginUrl("/login.html");
        //设置过滤器链
        //HashMap 无序   LinkedHashMap 有序
        //key：url    value：标签shiro的过滤器
        //anon是shiro的内置过滤器的名字，是anonymous单词前四个字母  表示能够匿名访问
        //main.html

        //把兜底的方法放map的最下方
        factoryBean.setFilterChainDefinitionMap(permMapFactoryBean().getObject());

        Map<String, Filter> filterMap=new HashMap<>();
        filterMap.put("jwt",jwtFilter());
        filterMap.put("perms",myPermissionsAuthorzationFilter());
        factoryBean.setFilters(filterMap);
        //
        return factoryBean;
    }



    //6.配置shiro注解的支持：shiro注解基于AOP实现的
    //6.1开启注解
//    @Bean
//    public AuthorizationAttributeSourceAdvisor advisor(SecurityManager securityManager){
//        AuthorizationAttributeSourceAdvisor sourceAdvisor=
//                new AuthorizationAttributeSourceAdvisor();
//        sourceAdvisor.setSecurityManager(securityManager);
//
//        return sourceAdvisor;
//    }
    //6.2创建代理器
//    @Bean
//    public DefaultAdvisorAutoProxyCreator creator(){
//        DefaultAdvisorAutoProxyCreator proxyCreator=new DefaultAdvisorAutoProxyCreator();
//        //开启目标代理
//        proxyCreator.setProxyTargetClass(true);
//        return proxyCreator;
//    }

    //7.配置session管理器
    //7.1将创建session管理器
//    @Bean//注意类是web类，不是session类
//    public DefaultWebSessionManager sessionManager(){
//        DefaultWebSessionManager manager=new DefaultWebSessionManager();
//        //过期时间：单位毫秒
//        manager.setGlobalSessionTimeout(1000*60*60*24);
//
//        manager.setDeleteInvalidSessions(true);
//
//        return manager;
//    }

//    //8.配置shiro标签的方言
//    @Bean
//    public ShiroDialect dialect(){
//        return new ShiroDialect();
//    }
}